/**
 * WebSocket 管理类
 * 负责建立连接、断线重连、心跳检测、消息收发
 */

class WebSocketManager {
  constructor() {
    this.ws = null
    this.url = ''
    this.token = '' // 保存token用于重连
    this.reconnectTimer = null
    this.heartbeatTimer = null
    this.heartbeatTimeoutTimer = null
    this.reconnectAttempts = 0
    this.maxReconnectAttempts = 10 // 增加重连次数
    this.reconnectInterval = 2000 // 2秒（缩短间隔）
    this.heartbeatInterval = 30000 // 30秒
    this.heartbeatTimeout = 10000 // 心跳超时时间10秒
    this.isManualClose = false
    this.isReconnecting = false // 是否正在重连
    this.listeners = new Map() // 消息监听器
    this.messageQueue = [] // 消息队列，用于连接断开时缓存消息
  }

  /**
   * 连接 WebSocket
   * @param {string} token - 用户认证令牌
   */
  connect(token) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      console.log('WebSocket 已连接')
      return Promise.resolve()
    }

    // 如果正在重连，不重复连接
    if (this.isReconnecting) {
      console.log('正在重连中...')
      return Promise.resolve()
    }

    return new Promise((resolve, reject) => {
      this.isManualClose = false
      this.token = token // 保存token
      
      // 使用环境变量构建WebSocket URL
      const baseURL = import.meta.env.VITE_API_BASE_URL || 'http://47.109.65.209:8080'
      const wsURL = baseURL.replace('http://', 'ws://').replace('https://', 'wss://')
      this.url = `${wsURL}/ws/message?token=${token}`
      
      console.log('🔌 尝试连接WebSocket:', this.url)

      try {
        this.ws = new WebSocket(this.url)
        this.setupEventHandlers()
        
        // 连接成功后resolve
        const onOpen = () => {
          this.ws.removeEventListener('open', onOpen)
          resolve()
        }
        this.ws.addEventListener('open', onOpen)
        
        // 连接失败后reject
        const onError = (error) => {
          this.ws.removeEventListener('error', onError)
          reject(error)
        }
        this.ws.addEventListener('error', onError, { once: true })
      } catch (error) {
        console.error('WebSocket 连接失败:', error)
        reject(error)
        this.reconnect()
      }
    })
  }

  /**
   * 设置 WebSocket 事件处理器
   */
  setupEventHandlers() {
    this.ws.onopen = () => {
      console.log('✅ WebSocket 连接成功')
      this.reconnectAttempts = 0
      this.isReconnecting = false
      this.startHeartbeat()
      this.emit('connected')
      
      // 发送队列中的消息
      this.flushMessageQueue()
    }

    this.ws.onmessage = (event) => {
      try {
        const message = JSON.parse(event.data)
        console.log('收到消息:', message)
        this.handleMessage(message)
        
        // 收到任何消息都重置心跳超时
        this.resetHeartbeatTimeout()
      } catch (error) {
        console.error('消息解析失败:', error)
      }
    }

    this.ws.onerror = (error) => {
      console.error('❌ WebSocket 错误:', error)
      this.emit('error', error)
    }

    this.ws.onclose = (event) => {
      console.log('🔌 WebSocket 连接关闭:', event.code, event.reason)
      this.stopHeartbeat()
      this.emit('closed', event)

      // 如果不是手动关闭，则尝试重连
      if (!this.isManualClose) {
        this.reconnect()
      }
    }
  }

  /**
   * 处理接收到的消息
   */
  handleMessage(message) {
    const { type, data, timestamp } = message

    switch (type) {
      case 'CONNECTED':
        console.log('✅ 连接确认:', data)
        break
      case 'NEW_MESSAGE':
        this.emit('newMessage', data)
        break
      case 'MESSAGE_SENT':
        this.emit('messageSent', data)
        break
      case 'MESSAGE_READ':
        this.emit('messageRead', data)
        break
      case 'PONG':
        // 心跳响应，重置超时计时器
        this.resetHeartbeatTimeout()
        break
      case 'ERROR':
        console.error('❌ 服务器错误:', data)
        this.emit('serverError', data)
        break
      default:
        console.warn('⚠️ 未知消息类型:', type)
    }
  }

  /**
   * 发送消息（自动重连）
   * @param {number} receiverId - 接收者ID
   * @param {string} content - 消息内容
   */
  async sendMessage(receiverId, content) {
    const message = {
      type: 'SEND_MESSAGE',
      data: {
        receiverId,
        content
      }
    }

    // 如果未连接，先尝试重连
    if (!this.isConnected()) {
      console.log('连接已断开，尝试重连...')
      
      // 将消息加入队列
      this.messageQueue.push(message)
      
      // 尝试重连
      try {
        if (this.token) {
          await this.connect(this.token)
          return true // 重连成功后消息会自动发送
        } else {
          console.error('无法重连：token不存在')
          return false
        }
      } catch (error) {
        console.error('重连失败:', error)
        return false
      }
    }

    // 已连接，直接发送
    try {
      this.ws.send(JSON.stringify(message))
      return true
    } catch (error) {
      console.error('发送消息失败:', error)
      // 发送失败，加入队列并尝试重连
      this.messageQueue.push(message)
      this.reconnect()
      return false
    }
  }

  /**
   * 发送队列中的消息
   */
  flushMessageQueue() {
    if (this.messageQueue.length === 0) return

    console.log(`📤 发送队列中的 ${this.messageQueue.length} 条消息`)
    
    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift()
      try {
        this.ws.send(JSON.stringify(message))
      } catch (error) {
        console.error('发送队列消息失败:', error)
        // 发送失败，放回队列
        this.messageQueue.unshift(message)
        break
      }
    }
  }

  /**
   * 发送心跳
   */
  sendHeartbeat() {
    if (this.isConnected()) {
      try {
        this.ws.send(JSON.stringify({ type: 'PING' }))
        // 设置心跳超时检测
        this.heartbeatTimeoutTimer = setTimeout(() => {
          console.warn('⚠️ 心跳超时，连接可能已断开')
          // 主动关闭并重连
          if (this.ws) {
            this.ws.close()
          }
        }, this.heartbeatTimeout)
      } catch (error) {
        console.error('发送心跳失败:', error)
      }
    }
  }

  /**
   * 重置心跳超时计时器
   */
  resetHeartbeatTimeout() {
    if (this.heartbeatTimeoutTimer) {
      clearTimeout(this.heartbeatTimeoutTimer)
      this.heartbeatTimeoutTimer = null
    }
  }

  /**
   * 启动心跳检测
   */
  startHeartbeat() {
    this.stopHeartbeat()
    this.heartbeatTimer = setInterval(() => {
      this.sendHeartbeat()
    }, this.heartbeatInterval)
  }

  /**
   * 停止心跳检测
   */
  stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer)
      this.heartbeatTimer = null
    }
    this.resetHeartbeatTimeout()
  }

  /**
   * 重新连接
   */
  reconnect() {
    if (this.isManualClose) {
      return
    }

    if (this.isReconnecting) {
      return
    }

    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.error('❌ 达到最大重连次数，停止重连')
      this.emit('reconnectFailed')
      // 清空消息队列
      this.messageQueue = []
      return
    }

    this.isReconnecting = true
    this.reconnectAttempts++
    console.log(`🔄 尝试重连... (${this.reconnectAttempts}/${this.maxReconnectAttempts})`)

    // 清除旧的重连定时器
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer)
    }

    this.reconnectTimer = setTimeout(async () => {
      if (this.token) {
        try {
          await this.connect(this.token)
          console.log('✅ 重连成功')
        } catch (error) {
          console.error('重连失败:', error)
          this.isReconnecting = false
          // 继续尝试重连
          this.reconnect()
        }
      } else {
        console.error('无法重连：token不存在')
        this.isReconnecting = false
      }
    }, this.reconnectInterval)
  }

  /**
   * 手动关闭连接
   */
  close() {
    this.isManualClose = true
    this.stopHeartbeat()

    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer)
      this.reconnectTimer = null
    }

    if (this.ws) {
      this.ws.close()
      this.ws = null
    }

    // 清空消息队列和token
    this.messageQueue = []
    this.token = ''
    this.reconnectAttempts = 0
    this.isReconnecting = false
    
    this.listeners.clear()
    console.log('WebSocket 已手动关闭')
  }

  /**
   * 检查连接状态
   */
  isConnected() {
    return this.ws && this.ws.readyState === WebSocket.OPEN
  }

  /**
   * 添加事件监听器
   * @param {string} event - 事件名称
   * @param {function} callback - 回调函数
   */
  on(event, callback) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, [])
    }
    this.listeners.get(event).push(callback)
  }

  /**
   * 移除事件监听器
   * @param {string} event - 事件名称
   * @param {function} callback - 回调函数
   */
  off(event, callback) {
    if (!this.listeners.has(event)) {
      return
    }

    const callbacks = this.listeners.get(event)
    const index = callbacks.indexOf(callback)
    if (index > -1) {
      callbacks.splice(index, 1)
    }
  }

  /**
   * 触发事件
   * @param {string} event - 事件名称
   * @param {any} data - 事件数据
   */
  emit(event, data) {
    if (!this.listeners.has(event)) {
      return
    }

    const callbacks = this.listeners.get(event)
    callbacks.forEach(callback => {
      try {
        callback(data)
      } catch (error) {
        console.error('事件回调执行失败:', error)
      }
    })
  }
}

// 创建单例
export const wsManager = new WebSocketManager()

// 初始化 WebSocket（在用户登录后调用）
export function initWebSocket(token) {
  wsManager.connect(token)
}

// 关闭 WebSocket（在用户登出时调用）
export function closeWebSocket() {
  wsManager.close()
}

